﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization;
using MimiDouban.Abstract.Beans;


[DataContract(Namespace = "doubanloginDll8")]
class Config
{
    [DataMember(Order = 0)]
    public string album
    {
        get;
        set;
    }
    [DataMember(Order = 1)]
    public string picture
    {
        get;
        set;
    }
    [DataMember(Order = 2)]
    public string ssid
    {
        get;
        set;
    }
    [DataMember(Order = 3)]
    public string artist
    {
        get;
        set;
    }
    [DataMember(Order = 4)]
    public string url
    {
        get;
        set;
    }
    [DataMember(Order = 5)]
    public string company
    {
        get;
        set;
    }
    [DataMember(Order = 6)]
    public string title
    {
        get;
        set;
    }
    [DataMember(Order = 7)]
    public string rating_avg
    {
        get;
        set;
    }
    [DataMember(Order = 8)]
    public string length
    {
        get;
        set;
    }
    [DataMember(Order = 9)]
    public string source_url
    {
        get;
        set;
    }
    [DataMember(Order = 10)]
    public string subtype
    {
        get;
        set;
    }
    [DataMember(Order = 11)]
    public string public_time
    {
        get;
        set;
    }
    [DataMember(Order = 12)]
    public string sid
    {
        get;
        set;
    }
    [DataMember(Order = 13)]
    public string aid
    {
        get;
        set;
    }
    [DataMember(Order = 14)]
    public string albumtitle
    {
        get;
        set;
    }
    [DataMember(Order = 15)]
    public string like
    {
        get;
        set;
    }
}

namespace doubanloginDll8
{
    /// <summary>
    /// 用于实现豆瓣协议的核心类
    /// </summary>
	public class DoubanProtocol
	{	
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="u">用户名</param>
        /// <param name="p">密码</param>
        /// <returns>登录状态</returns>
		public DoubanUser login(string u,string p)
		{  
            string s = HttpWebResponseUtility.getInstance().CreateGetHttpResponse("http://douban.fm");
            Dictionary<string,string> parameters = new Dictionary<string,string>();
            parameters.Add("source", "radio");
            parameters.Add("form_email", u);
            parameters.Add("form_password", p);
            parameters.Add("remember", "on");
            string loginActionUrl = "https://www.douban.com/accounts/login";
            string respBody = HttpWebResponseUtility.getInstance().CreatePostHttpResponse(loginActionUrl,parameters);
            int index = respBody.IndexOf("id=\"fm-user\">");
            if (index > 0)
            {
                DoubanUser user = new DoubanUser();
                user.Email = u;
                user.Password = p;
                int usernameStart = index + "id=\"fm-user\">".Length;
                int usernameLength = respBody.IndexOf('<',usernameStart) - usernameStart;
                user.Username = respBody.Substring(usernameStart, usernameLength);
                return user;
            }
            else
            {
                return null;
            }
		}

        public string checkLogin()
        {
            string respBody = "";
            try
            {
            	respBody = HttpWebResponseUtility.getInstance().CreateGetHttpResponse("http://douban.fm");
            }
            catch (System.Exception ex)
            {
                MimiDouban.Test.TestLog.getInstance().error("getInitPlayList catch", ex);
            }
            if (respBody.IndexOf("立即开启") >= 0)
            {
                return null;
            }

            int index = respBody.IndexOf("id=\"fm-user\">");
            if (index > 0)
            {
                int usernameStart = index + "id=\"fm-user\">".Length;
                int usernameLength = respBody.IndexOf('<', usernameStart) - usernameStart;
                string username = respBody.Substring(usernameStart, usernameLength);
                return username;
            }
            else
            {
                return null;
            }
        }
        

        /// <summary>
        /// 返回第一个播放列表
        /// </summary>
        /// <param name="channel">初始频道ID</param>
        /// <returns>第一个播放列表</returns>
		public DoubanPlayList getInitPlayList ( int channel )
		{
            HttpWebResponseUtility.getInstance().CreateGetHttpResponse("http://douban.fm/radio");

            string url = String.Format("http://douban.fm/j/mine/playlist?type=n&channel={0}&h=&from=radio&r={1}", channel, getR());
            String respBody = "";
            try
            {
            	respBody = HttpWebResponseUtility.getInstance().CreateGetHttpResponse(url);            	
            }
            catch (System.Exception ex)
            {
                MimiDouban.Test.TestLog.getInstance().error("getInitPlayList catch", ex);
            }
			return getSongJson(respBody);
		}

        /// <summary>
        /// 更改频道
        /// </summary>
        /// <param name="channel">新的频道ID</param>
        /// <returns>新的播放列表</returns>
        public DoubanPlayList changeChannel(int channel)
        {
            string url = String.Format("http://douban.fm/j/mine/playlist?type=n&channel={0}&h=&from=radio&r={1}", channel, getR());

            String respBody = HttpWebResponseUtility.getInstance().CreateGetHttpResponse(url);
            return getSongJson(respBody);
        }

		/// <summary>
		/// 喜欢，需要长报告
		/// </summary>
		/// <param name="sid">歌曲ID</param>
		/// <param name="channel">当前频道号</param>
		/// <param name="historylist">播放历史列表</param>
		/// <returns>新的播放列表</returns>
		public DoubanPlayList like ( string sid, int channel ,DoubanPlayedList historylist )
		{
            //先构造history
            string history = "";
            foreach (DoubanPlayedSong dps in historylist.PlayedSongs)
            {
                history += "|" + dps.Sid + ":" + dps.Type;
            }
            history += "|" + sid + ":r";

            //构造url
            string url = String.Format("http://douban.fm/j/mine/playlist?type=r&sid={0}&h={1}&channel={2}&from=radio&r={3}",sid,history,channel,getR());

            String respBody = HttpWebResponseUtility.getInstance().CreateGetHttpResponse(url);
            return getSongJson(respBody);
		}

        /// <summary>
        /// 取消喜欢，需要长报告
        /// </summary>
        /// <param name="sid">歌曲ID</param>
        /// <param name="channel">当前频道号</param>
        /// <param name="historylist">播放历史列表</param>
        /// <returns>新的播放列表</returns>
        public DoubanPlayList likeCancle(string sid, int channel ,DoubanPlayedList historylist)
        {
            //先构造history
            string history = "";
            foreach (DoubanPlayedSong dps in historylist.PlayedSongs)
            {
                history += "|" + dps.Sid + ":" + dps.Type;
            }
            history += "|" + sid + ":u";

            //构造url
            string url = String.Format("http://douban.fm/j/mine/playlist?type=u&sid={0}&h={1}&channel={2}&from=radio&r={3}", sid, history, channel, getR());

            String respBody = HttpWebResponseUtility.getInstance().CreateGetHttpResponse(url);
            return getSongJson(respBody); 
        }

        /// <summary>
        /// 不喜欢，需要长报告
        /// </summary>
        /// <param name="sid">歌曲ID</param>
        /// <param name="channel">当前频道号</param>
        /// <param name="historylist">播放历史列表</param>
        /// <returns>新的播放列表</returns>
        public DoubanPlayList disLike(string sid, int channel, DoubanPlayedList historylist)
        {
            string url1 = "http://douban.fm/j/mine/playlist?type=b&sid=";
            string url2 = "&h=";
            string history = "";
            string url3 = "&channel=";
            string url4 = "&r=93a6fc1367";

            foreach (DoubanPlayedSong dps in historylist.PlayedSongs)
            {
                history += "|" + dps.Sid + ":" + dps.Type;
            }
            history += "|" + sid + ":r";

            string url = url1 + sid + url2 + history + url3 + channel + url4;
            
            String respBody = HttpWebResponseUtility.getInstance().CreateGetHttpResponse(url);
            return getSongJson(respBody); 
		}

        /// <summary>
        /// 下一首，需要长报告
        /// </summary>
        /// <param name="sid">歌曲ID</param>
        /// <param name="channel">当前频道号</param>
        /// <param name="historylist">播放历史列表</param>
        /// <returns>新的播放列表</returns>
        public DoubanPlayList nextSong(string sid, int channel, DoubanPlayedList historylist)
        {
            //先构造history
            string history = "";
            foreach (DoubanPlayedSong dps in historylist.PlayedSongs)
            {
                history += "|" + dps.Sid + ":" + dps.Type;
            }
            //构造url
            string url = String.Format("http://douban.fm/j/mine/playlist?type=s&sid={0}&h={1}&channel={2}&from=radio&r={3}", sid, history, channel, getR());

            String respBody = HttpWebResponseUtility.getInstance().CreateGetHttpResponse(url);
            return getSongJson(respBody);
        }

        /// <summary>
        /// 现有的播放列表已经完成，需要长报告
        /// </summary>
        /// <param name="sid">歌曲ID</param>
        /// <param name="channel">当前频道号</param>
        /// <param name="historylist">播放历史列表</param>
        /// <returns>新的播放列表</returns>
        public DoubanPlayList songFinished(string sid, int channel, DoubanPlayedList historylist)
        {
            //先构造history
            string history = "";
            foreach (DoubanPlayedSong dps in historylist.PlayedSongs)
            {
                history += "|" + dps.Sid + ":" + dps.Type;
            }

            //构造url
            string url = String.Format("http://douban.fm/j/mine/playlist?type=p&sid={0}&h={1}&channel={2}&from=radio&r={3}", sid, history, channel, getR());
            String respBody = HttpWebResponseUtility.getInstance().CreateGetHttpResponse(url);
            return getSongJson(respBody);
        }

        /// <summary>
        /// 当前歌曲播放完了，但是播放列表中还有剩下的歌曲，短报告
        /// </summary>
        /// <param name="sid">歌曲ID</param>
        /// <param name="channel">当前频道号</param>
        public void songFinished(string sid,int channel)
        {
            string url = String.Format("http://douban.fm/j/mine/playlist?type=e&sid={0}&channel={1}&from=radio&r={2}", sid, channel, getR());
            HttpWebResponseUtility.getInstance().CreateGetHttpResponse(url);
        }

        /// <summary>
        /// 把Json的数据转换成DoubanPlaylist对象
        /// </summary>
        /// <param name="sb"></param>
        /// <returns></returns>
        private DoubanPlayList getSongJson(String sb)
        {
            int start = sb.IndexOf('[');
            int end = sb.LastIndexOf(']');
            string jsonstring; 
            try
            {
            	jsonstring = sb.Substring(start + 1, end - start - 1);
            }
            catch (System.Exception ex)
            {
                return null;
            }
            string[] jsonSongs = jsonstring.Split(new string[] { "}," }, StringSplitOptions.RemoveEmptyEntries);
            DoubanPlayList doubanList = new DoubanPlayList();

            for (int i = 0; i < jsonSongs.Length; i++)
            {
                string jsonsong = jsonSongs[i];
                string padjsonsong = "";

                if (jsonsong.Contains('}') == false)
                {
                    padjsonsong = jsonsong.PadRight(jsonsong.Length + 1, '}');
                }
                else
                {
                    padjsonsong = jsonsong;
                }

                try
                {
                    var mStream = new MemoryStream(Encoding.UTF8.GetBytes(padjsonsong));
                    var serializer = new DataContractJsonSerializer(typeof(Config));
                    Config readConfig = (Config)serializer.ReadObject(mStream);

                    DoubanSong ds = new DoubanSong();
                    ds.Album = readConfig.album;
                    ds.Picture = readConfig.picture;
                    ds.Ssid = readConfig.ssid;
                    ds.Artist = readConfig.artist;
                    ds.Url = readConfig.url;
                    ds.Company = readConfig.company;
                    ds.Title = readConfig.title;

                    if (readConfig.rating_avg != null)
                    {
                        ds.Rating_avg = Double.Parse(readConfig.rating_avg);
                    }
                    if (readConfig.length != null)
                    {
                        ds.Length = int.Parse(readConfig.length);
                    }
                    ds.Source_url = readConfig.source_url;
                    ds.Subtype = readConfig.subtype;
                    ds.Public_time = readConfig.public_time;
                    ds.Sid = readConfig.sid;
                    ds.Aid = readConfig.aid;
                    ds.Albumtitle = readConfig.albumtitle;
                    ds.Like = readConfig.like;
                    doubanList.Songs.Add(ds);
                }
                catch
                {
                    return null;
                }
            }

            return doubanList;
        }

        /// <summary>
        /// 生成一个随机串
        /// </summary>
        /// <returns>生成的随机串</returns>
        private string getR()
        {
            StringBuilder result = new StringBuilder();
            Random rand = new Random(DateTime.Now.Millisecond);
            byte[] bytes = new byte[5];
            rand.NextBytes(bytes);
            for (int i = 0; i < 5; i++)
            {
                if (bytes[i] <= 15)
                {
                    result.Append("0" + Convert.ToString(bytes[i], 16));
                }
                else
                {
                    result.Append(Convert.ToString(bytes[i], 16));
                }
            }
            return result.ToString().ToLower();
        }

        public void end()
        {
            HttpWebResponseUtility.getInstance().end();
        }
    }
}
